#ifndef ATOMIC_H
#define ATOMIC_H

inline __attribute__ ((always_inline))
int fetch_and_store(int *p, int val)
{
  int ret;

  asm __volatile__("xchgl %0, %1"
           : "=r"(ret), "=m"(*p)
           : "0"(val), "m"(*p)
           : "memory");

  return ret;
}

inline __attribute__ ((always_inline))
int compare_and_swap (int *p, int oldval, int newval)
{
  char ret;
  int readval;

  asm __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
	       : "=q" (ret), "=m" (*p), "=a" (readval)
	       : "r" (newval), "m" (*p), "a" (oldval)
	       : "memory");

  return ret;
}

/*
#define low_power_spin(p) asm __volatile__ ("L1:\n" \
                                            "move %0, %3;"\
                                            "move $0, %1;"\
                                            "move $0, %2;"\
                                            "monitor %3, %1, %2;" \
                                            "cmpl $1, (%0);" \
                                            "jnz L2;"\
                                            "move $0, %3;"\
                                            "move $0, %1;"\
                                            "mwait %3, %1;" \
                                            "cmpl $1, (%0);" \
                                            "jz L1;"\
                                            "L2:\n"\
           :\
           : "r" (p), "c" (0), "d" (0), "a" (0) \
           : "memory");
           */
           

#define low_power_spin(p) asm __volatile__ ("L1:\n" \
                                            "movl %0, %%eax;" \
                                            "movl $0, %1;" \
                                            "movl $0, %2;" \
                                            "monitor %%eax, %1, %2;" \
                                            "cmpl $1, (%0);" \
                                            "jnz L2;"\
                                            "movl $0, %%eax;" \
                                            "movl $0, %1;" \
                                            "mwait %%eax, %1;" \
                                            "cmpl $1, (%0);" \
                                            "jz L1;"\
                                            "L2:\n"\
           :\
           : "r" (p), "c" (0), "d" (0) \
           : "eax", "memory");

inline __attribute__ ((always_inline))
void spin (int *p)
{
    while (*p)
    {
        asm __volatile__ ("" : "=m" (*p) : "m" (*p));
    }
}

/*
inline __attribute__ ((always_inline))
int fetch_and_increment (int *p) {
   
   long int ret, old_value, inced_value;
   
   asm __volatile__ ("Lfetch1: \n" \
                     "movl %1, %2;" \
                     "movl %2, %3;" \
                     "incl %3;" \
                     "lock; cmpxchg %3, %1;"\
                     "jnz Lfetch1;"\
                     "sete %0;"\
	       : "=q" (ret), "=m" (*p), "=a" (old_value), "=q" (inced_value) \
	       : "m" (*p) \
	       : "memory");      
   
   return ret;

}
*/


#define f_and_i 

int fetch_and_increment (int *p) {
   
   long int ret, old_value, inced_value;
   
   asm __volatile__ ("Lfetch1: \n" \
                     "movl %0, %1;" \
                     "movl %1, %2;" \
                     "incl %2;" \
                     "lock; cmpxchg %2, %0;"\
                     "jnz Lfetch1;"\
	       : "=m" (*p), "=a" (old_value), "=q" (inced_value) \
	       : "m" (*p) \
	       : "memory");      
   
   return old_value;

}



#endif // ifndef ATOMIC_H
